﻿#pragma once


#include <QObject>
#include <QDebug>
#include <QThread>

#ifdef Q_OS_MAC
#include <CoreAudio/CoreAudio.h>
#include <AudioToolbox/AudioToolbox.h>
#endif


extern "C"
{
#include <libavutil/time.h>
#include <libavutil/frame.h>
#include <libavutil/avutil.h>
#include <libavformat/avformat.h>

};

#include "MacMediaDevice.h"

#define OutputBus 0
#define InputBus 1

#define DEVICE_INPUT_SCOPE kAudioDevicePropertyScopeInput
#define DEVICE_OUPUT_SCOPE kAudioObjectPropertyScopeOutput

class LoopBuffer;
class AVAudioConvert;

class MacAudio: public MacMediaDevice
{
Q_OBJECT
    
    enum CoreAudioIO
    {
        INPUT_IO,
        OUTPUT_IO,
    };
    
public:
    explicit MacAudio(QObject *parent = 0);

    virtual ~MacAudio();
            
    virtual void setDeviceId(const QString &deviceId) override;
    virtual QString getDeviceId() override;
    
    void release();

protected:
    virtual bool init() override;
    virtual bool capture() override;
    
signals:
    void GotAVFrame(AVFrame *frame);
    
public slots:
    virtual void run() override;
private:
    UInt32 convertChannelLayout(UInt32 channelsPerFrame);
    
    AVSampleFormat convertFormat(AudioFormatFlags flags, UInt32 bits);
        
    OSStatus enableAUIO(MacAudio::CoreAudioIO type, bool enable);
    
    bool initAudioUnit();
    
    bool initFormat();
    
    bool initCallback();
    
    bool initAudioBufferList();
    
public:
    AudioUnit       unit = nullptr;
    AVSampleFormat  format = (AVSampleFormat)0;
    UInt32          sampleRate = 0;
    uint64_t        channelLayout = 0;
    AudioBufferList *bufferList = nullptr;

    int8_t          channel = 0;
    LoopBuffer  *m_buffer = nullptr;
    AVAudioConvert   *m_convert = nullptr;
    
private:
    AudioDeviceID  deviceId;
    QString        deviceName;
};
